parser grammar ScIom;

options {
    output=AST;
    ASTLabelType=CommonTree;
    tokenVocab=ScIom;
}

@header {
package org.sciom.parser;

import java.io.Reader;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.FileReader;
import java.io.PrintStream;
import java.io.StringReader;

}

@members {
    public static ScIomParser parserFor(String str) throws Exception {
        return parserFor(new StringReader(str));
    }

    public static ScIomParser parserFor(Reader str) throws Exception {
        ScIomLexer lexer = new ScIomLexer(new ANTLRReaderStream(str));
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        return new ScIomParser(tokens);
    }

    public org.antlr.runtime.tree.Tree nextTree() throws Exception {
        int type = -1;
        while((type = input.LT(1).getType()) == Terminator) {
            input.consume();
        }
        if(type != EOF) {
            return (CommonTree)(this.prog().getTree());
        }
        return null;
    }

    public static void main(final String[] args) throws Exception {
        Reader reader;
        if(args.length > 0) {
            reader = new BufferedReader(new FileReader(args[0]));
        } else {
            reader = new InputStreamReader(System.in);
        }
        ScIomLexer lexer = new ScIomLexer(new ANTLRReaderStream(reader));
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        ScIomParser parser = new ScIomParser(tokens);
        ScIomParser.prog_return r = parser.prog();

        CommonTree tree = (CommonTree)r.getTree();
//        System.err.println(tree.toStringTree());
    }
}

prog : message_chain;

// statements : (message_chain Terminator!+)*;

message_chain : expression+ -> ^(EXPR expression+);

expression : (symbol empty_parens?)
    | parens
    ;

empty_parens : (OpenParen Terminator* CloseParen) -> ^(OpenParen) ;

parens : (OpenParen Terminator* parens_inside Terminator* CloseParen) -> ^(OpenParen parens_inside);

parens_inside : message_chain (Comma! Terminator!* message_chain)* ;

symbol : (Identifier | Number | HexNumber | quote) ;

quote : MonoQuote | TriQuote ;

